package cn.hejiang.mamis.core.config;

import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.sql.DataSource;

import org.springframework.boot.autoconfigure.sql.init.SqlDataSourceScriptDatabaseInitializer;
import org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class SqlDatabaseInitializer extends SqlDataSourceScriptDatabaseInitializer {
	private Boolean _needToRunScripts = null;

	public SqlDatabaseInitializer(DataSource dataSource, SqlInitializationProperties properties) {
		super(dataSource, setupProperties(properties));
	}

	@Override
	protected void runScripts(List<Resource> resources, boolean continueOnError, String separator, Charset encoding) {
		if (!needToRunScripts()) {
			resources.forEach(res -> log.info("no need to run script {}", res.getFilename()));
			return;
		}

		try {
			super.runScripts(resources, continueOnError, separator, encoding);
		} catch (Exception e) {
			log.error(e.getLocalizedMessage(), e);
			_needToRunScripts = false;
		}
	}

	private static SqlInitializationProperties setupProperties(SqlInitializationProperties properties) {
		List<String> schemaLocations = Arrays.asList(new String[] { "classpath:./schema-mysql.sql" });
		List<String> dataLocations = Arrays.asList(new String[] { "classpath:./data-mysql.sql" });

		properties.setMode(DatabaseInitializationMode.ALWAYS);
		properties.setSchemaLocations(schemaLocations);
		properties.setDataLocations(dataLocations);
		properties.setEncoding(Charset.forName("utf-8"));

		return properties;
	}

	private boolean needToRunScripts() {
		if (_needToRunScripts != null) {
			return _needToRunScripts;
		}

		String[] tables = new String[] { "magic_api_file", "plat_sys", "plat_user", "spring_session",
				"spring_session_attributes", "sys_dept", "sys_menu", "sys_page", "sys_role", "sys_role_menu",
				"sys_role_user" };
		Set<String> set = Arrays.asList(tables).stream().collect(Collectors.toSet());

		try (Connection conn = this.getDataSource().getConnection();) {
			DatabaseMetaData dbmd = conn.getMetaData();
			try (ResultSet rs = dbmd.getTables(conn.getCatalog(), conn.getSchema(), "%", new String[] { "TABLE" });) {
				// ResultSetMetaData rsmd = rs.getMetaData();
				while (rs.next()) {
					String table = rs.getString("TABLE_NAME");
					if (set.contains(table.toLowerCase())) {
						set.remove(table);
					} else {
						log.debug("table {} doesn't exist", table);
					}
				}
			}
		} catch (SQLException e) {
			log.error(e.getLocalizedMessage(), e);
		}

		_needToRunScripts = set.size() > 0;
		return _needToRunScripts;
	}
}
